
第16章中，讨论了类模板如何偏特化，函数模板则可以重载。这两种机制有些不同。

偏特化不会引入新模板，其为现有模板(主模板)的扩展。当查找类模板时，首先考虑主模板。若选择了主模板后，发现该模板的偏特化具有与实例化匹配的模板参数模式时，则实例化其定义，而非主模板的定义。(与全特化模板的工作方式完全相同)

相反，重载函数模板是完全独立的模板。在实例化模板时，将所有重载模板放在一起，重载解析尝试选择最适合的模板。乍一看，这似乎有充足的选择，但在实践中会有一些限制:

\begin{itemize}
\item 
可以特化类的成员模板，而不需要更改该类的定义，但添加重载成员确实需要更改类的定义。这不是一个好选择，因为可能不能这样做。此外，C++标准目前不允许向std命名空间添加新模板，但它允许对该命名空间模板进行特化。

\item 
要重载函数模板，其函数参数必须在某些重要方面有所不同。考虑一个函数模板R convert(T const\&)，其中R和T是模板参数。我们可能很想特化R = void的模板，但这不能使用重载来完成。

\item 
对于非重载函数的代码，在函数重载时不再有效。具体来说，给定两个函数模板f(T)和g(T)(其中T是一个模板参数)，表达式g(\&f<int>)只有在f没有重载时才有效(否则，无法确定f是哪个)。

\item 
友元声明指的是特定函数模板或特定函数模板的实例化。函数模板的重载版本不会自动拥有原始模板的权限。
\end{itemize}

列表共同构成了一个强有力的论据，支持函数模板的偏特化构造。

偏特化函数模板的一种自然语法是泛化类模板表示法:

\begin{lstlisting}[style=styleCXX]
template<typename T>
T const& max (T const&, T const&); // primary template

template<typename T>
T* const& max <T*>(T* const&, T* const&); // partial specialization
\end{lstlisting}

一些语言设计人员担心这种偏特化方法与函数模板重载的交互。例如:

\begin{lstlisting}[style=styleCXX]
template<typename T>
void add (T& x, int i); // a primary template

template<typename T1, typename T2>
void add (T1 a, T2 b); // another (overloaded) primary template

template<typename T>
void add<T*> (T*&, int); // Which primary template does this specialize?
\end{lstlisting}

然而，我们希望将这样的情况视为错误，不会对功能的使用产生重大影响。

这个扩展在C++11的标准化过程中简要地讨论过，但是最后却没有引起多少人的兴趣。不过，因为其巧妙地解决了一些常见的编程问题，这个话题偶尔还会出现。这个特性也许会在未来的C++标准中采纳。






















